
package jtrimet;

import java.util.*;

import org.apache.http.client.*;
import org.apache.http.client.methods.*;
import org.apache.http.client.params.AllClientPNames;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;

import com.thoughtworks.xstream.XStream;


public class TrimetClient 
{

	
	static
	{
	  System.getProperties().setProperty("org.apache.commons.logging.simplelog.defaultlog", "debug");
	  System.getProperties().setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
	}

	private static final String APP_ID = "4DDC3FF2BE33E6E2809A91D95";
	
	private HttpClient httpClient = null;
	private String appId = APP_ID;

	
	public TrimetClient()
	{
		this(null);
	}
	
	
	public TrimetClient(HttpClient client)
	{
		if (client == null)
		{
			client = createHttpClient();
		}
		httpClient = client;
		
		setUserAgent("jtrimet");
		setConnectionTimeout( 5 * 1000);
		setSocketTimeout(20 * 1000);
		
		if (httpClient instanceof DefaultHttpClient)
		{
			DefaultHttpClient defaultClient = (DefaultHttpClient) httpClient;
			
			// defaultClient.addRequestInterceptor(GzipRequestInterceptor.getInstance());
			// defaultClient.addResponseInterceptor(GzipResponseInterceptor.getInstance());
			
		}
		

	}
	
	public List<Location> getArrivalInformation(String... locationIds)
	{
		
		StringBuffer url = new StringBuffer();
		url.append(URLs.ARRIVALS_BASE_URL);
		url.append("/locIDs/");
		
		if (locationIds.length < 1)
		{
			throw new IllegalArgumentException();
		}
		
		for (int i = 0; i < locationIds.length; i++)
		{
			url.append(locationIds[i]);
			if (i != (locationIds.length - 1))
			{
				url.append(",");
			}
		}
		
		appendAppId(url);
		
		try
		{
			
			String xmlResponse = executeGet(url);
			
			Response r = fromXml(xmlResponse);
			
			return r.getLocations();
		}
		catch (Exception ex)
		{
			throw new RuntimeException(ex);
		}
		
		
		
	}
	
	protected Response fromXml(String xmlResponse)
	{
		System.out.println(xmlResponse);
		
		XStream xstream = XStreamFactory.createXStream();
		
		Response r = (Response) xstream.fromXML(xmlResponse);
		
		return r;
	}


	/**
	 * 
	 *  @return list of Location objects
	 *  
	 */
	public List<Location> getNearbyStops(String latitude, String longitude, long distanceInMeters)
	{
		StringBuffer url = new StringBuffer();
		url.append(URLs.STOPS_BASE_URL);

		appendAppId(url);
		
		url.append("/ll/");

		url.append(latitude);
		url.append(",");
		url.append(longitude);
		
		if (distanceInMeters <= 0)
		{
			distanceInMeters = 1;
		}
		
		url.append("/meters/" + distanceInMeters);
		
		String xmlResponse = executeGet(url);
		
		Response r = fromXml(xmlResponse);
		
		return r.getLocations();
		
	}
	
	public List<Location> getNearbyStops(GeoLocation location, long distanceInMeters)
	{
		return getNearbyStops("" + location.getLatitude(), "" + location.getLongitude(), distanceInMeters);
	}
	
	protected String executeGet(CharSequence url) 
	{
		HttpClient c = getHttpClient();
		
		System.out.println(url);
		
		try {

			HttpGet get = new HttpGet(url.toString());
			
			HttpResponse response = c.execute(get);

			StatusLine statusLine = response.getStatusLine();
			
			System.out.println("GET response status code = " + statusLine.getStatusCode());
			
			HttpEntity entity = response.getEntity();

			String responseString = EntityUtils.toString(entity);
			
			return responseString;
			
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	protected HttpClient createHttpClient()
	{
		DefaultHttpClient client = new org.apache.http.impl.client.DefaultHttpClient();

		return (HttpClient) client;
	}

	protected HttpClient getHttpClient()
	{
		return httpClient;
	}
	
	protected void appendAppId(StringBuffer s)
	{
		if (s.charAt(s.length() - 1) != '/')
		{
			s.append('/');
		}
		s.append("appId/");
		s.append(getAppId());
	}


	public String getAppId()
	{
		return appId;
	}


	public void setAppId(String id)
	{
		this.appId = id;
	}
	

	public void shutdown()
	{
		try
		{
			this.httpClient.getConnectionManager().shutdown();
		}
		catch (Exception ignore)
		{
			// ignored
		}
		
	}
	
	public void setUserAgent(String ua)
	{
		this.httpClient.getParams().setParameter(AllClientPNames.USER_AGENT, ua);
	}
	
	public void setConnectionTimeout(int milliseconds)
	{
		httpClient.getParams().setIntParameter(AllClientPNames.CONNECTION_TIMEOUT, milliseconds);
	}
	
	public void setSocketTimeout(int milliseconds)
	{
		httpClient.getParams().setIntParameter(AllClientPNames.SO_TIMEOUT, milliseconds);
	}
	
}
